a11y: Set an accessible role for GtkEntry
authorMatthias Clasen <mclasen@redhat.com>
Tue, 28 Jul 2020 20:11:45 +0000 (16:11 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Tue, 28 Jul 2020 22:16:37 +0000 (18:16 -0400)
Use the text-box accessible role for GtkEntry and
set the placeholder and read-only accessible properties.

Update the documentation and add tests.

docs/reference/gtk/section-accessibility.md
gtk/gtkentry.c
gtk/gtkenums.h
testsuite/a11y/entry.c [new file with mode: 0644]
testsuite/a11y/meson.build

index b8879731d303e9f00a9a22512d2816c13731bdde..78cb8c66fa7fc0f65de44165927a53ac998dfd9c 100644 (file)
@@ -58,6 +58,7 @@ Each role name is part of the #GtkAccessibleRole enumeration.
 | `SEPARATOR` | A divider that separates sections of content or groups of items | #GtkSeparator |
 | `SPIN_BUTTON` | A range control that allows seelcting among discrete choices | #GtkSpinButton |
 | `SWITCH` | A control that represents on/off values | #GtkSwitch |
+| `TEXT_BOX` | A type of input that allows free-form text as its value. | #GtkEntry |
 | `WINDOW` | An application window | #GtkWindow |
 | `...` | … |
 
index 5c940fbb0a1dc2ee19d77b1f5b0406ab013986d5..f4acb4c17a0102f120d6960fb83315aec4f8566c 100644 (file)
  * applied to the whole text. Note that specifying ranges does not make much
  * sense with translatable attributes. Use markup embedded in the translatable
  * content instead.
+ *
+ * # Accessibility
+ *
+ * GtkEntry uses the #GTK_ACCESSIBLE_ROLE_TEXT_BOX role.
  */
 
 #define MAX_ICONS 2
@@ -983,6 +987,7 @@ gtk_entry_class_init (GtkEntryClass *class)
                   GTK_TYPE_ENTRY_ICON_POSITION);
 
   gtk_widget_class_set_css_name (widget_class, I_("entry"));
+  gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_TEXT_BOX);
 }
 
 static GtkEditable *
@@ -1016,7 +1021,16 @@ gtk_entry_set_property (GObject         *object,
   GtkEntryPrivate *priv = gtk_entry_get_instance_private (entry);
 
   if (gtk_editable_delegate_set_property (object, prop_id, value, pspec))
-    return;
+    {
+      if (prop_id == PROP_EDITING_CANCELED + 1 + GTK_EDITABLE_PROP_EDITABLE)
+        {
+          gtk_accessible_update_property (GTK_ACCESSIBLE (entry),
+                                          GTK_ACCESSIBLE_PROPERTY_READ_ONLY, !g_value_get_boolean (value),
+                                          -1);
+        }
+
+      return;
+    }
 
   switch (prop_id)
     {
@@ -1028,7 +1042,6 @@ gtk_entry_set_property (GObject         *object,
     case PROP_ACTIVATES_DEFAULT:
     case PROP_TRUNCATE_MULTILINE:
     case PROP_OVERWRITE_MODE:
-    case PROP_PLACEHOLDER_TEXT:
     case PROP_IM_MODULE:
     case PROP_INPUT_PURPOSE:
     case PROP_INPUT_HINTS:
@@ -1038,6 +1051,10 @@ gtk_entry_set_property (GObject         *object,
       g_object_set_property (G_OBJECT (priv->text), pspec->name, value);
       break;
 
+    case PROP_PLACEHOLDER_TEXT:
+      gtk_entry_set_placeholder_text (entry, g_value_get_string (value));
+      break;
+
     case PROP_HAS_FRAME:
       gtk_entry_set_has_frame (entry, g_value_get_boolean (value));
       break;
@@ -3381,6 +3398,10 @@ gtk_entry_set_placeholder_text (GtkEntry    *entry,
   g_return_if_fail (GTK_IS_ENTRY (entry));
 
   gtk_text_set_placeholder_text (GTK_TEXT (priv->text), text);
+
+  gtk_accessible_update_property (GTK_ACCESSIBLE (entry),
+                                  GTK_ACCESSIBLE_PROPERTY_PLACEHOLDER, text,
+                                  -1);
 }
 
 /**
index 3d3b72b71c5c909c706b7db1a61705c247fe36bd..7947e01e82218623345e48fff5e108c7866427e7 100644 (file)
@@ -1235,7 +1235,8 @@ typedef enum {
  * @GTK_ACCESSIBLE_ROLE_TABLE: Unused
  * @GTK_ACCESSIBLE_ROLE_TAB_LIST: Unused
  * @GTK_ACCESSIBLE_ROLE_TAB_PANEL: Unused
- * @GTK_ACCESSIBLE_ROLE_TEXT_BOX: Unused
+ * @GTK_ACCESSIBLE_ROLE_TEXT_BOX: A type of input that allows free-form text
+ *    as its value.
  * @GTK_ACCESSIBLE_ROLE_TIME: Unused
  * @GTK_ACCESSIBLE_ROLE_TIMER: Unused
  * @GTK_ACCESSIBLE_ROLE_TOOLBAR: Unused
diff --git a/testsuite/a11y/entry.c b/testsuite/a11y/entry.c
new file mode 100644 (file)
index 0000000..67cfdcc
--- /dev/null
@@ -0,0 +1,41 @@
+#include <gtk/gtk.h>
+
+static void
+entry_role (void)
+{
+  GtkWidget *widget = gtk_entry_new ();
+  g_object_ref_sink (widget);
+
+  gtk_test_accessible_assert_role (widget, GTK_ACCESSIBLE_ROLE_TEXT_BOX);
+
+  g_object_unref (widget);
+}
+
+static void
+entry_properties (void)
+{
+  GtkWidget *widget = gtk_entry_new ();
+  g_object_ref_sink (widget);
+
+  gtk_test_accessible_assert_property (widget, GTK_ACCESSIBLE_PROPERTY_PLACEHOLDER, NULL);
+  gtk_test_accessible_assert_property (widget, GTK_ACCESSIBLE_PROPERTY_READ_ONLY, FALSE);
+
+  gtk_entry_set_placeholder_text (GTK_ENTRY (widget), "Hello");
+  gtk_editable_set_editable (GTK_EDITABLE (widget), FALSE);
+
+  gtk_test_accessible_assert_property (widget, GTK_ACCESSIBLE_PROPERTY_PLACEHOLDER, "Hello");
+  gtk_test_accessible_assert_property (widget, GTK_ACCESSIBLE_PROPERTY_READ_ONLY, TRUE);
+
+  g_object_unref (widget);
+}
+
+int
+main (int argc, char *argv[])
+{
+  gtk_test_init (&argc, &argv, NULL);
+
+  g_test_add_func ("/a11y/entry/role", entry_role);
+  g_test_add_func ("/a11y/entry/properties", entry_properties);
+
+  return g_test_run ();
+}
index e56f145c82698ca2273ecd253df172e379e2eb0d..81384c7bbf182ed17f3b4d802e109f6f1742d7ae 100644 (file)
@@ -14,6 +14,7 @@ tests = [
   { 'name': 'button' },
   { 'name': 'checkbutton' },
   { 'name': 'dialog' },
+  { 'name': 'entry' },
   { 'name': 'image' },
   { 'name': 'progressbar' },
   { 'name': 'scrollbar' },